#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/stat.h>
#include <dirent.h>

#include <iostream>
#include <string.h>
#include <assert.h>
#include <map>
#include <fstream>
#include <set>
#include <vector>

#include "mpi.h"

using namespace std;

extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;

//the default directory is a empty string.
char buffer[1024*1024];

char dir[1024];

//the destination directory that all threads need to copy files to
char dest_dir[1024];

int rank; //the rank of me(i.e., this process)
int size; //the number of processes in all


int to = 0;   //the destination rank
int from = 0; //the source rank
int count = 0;//the count of elements to be sent/received
int tag = 0;  //the tag of the message

int st_count, st_source, st_tag; //the information of the message that actually recieved.
MPI::Status status; //the status of the received message

vector<string> filepaths;

void process_this_file(string filename)
{
	
	fstream file(filename.c_str(), ios::in);
	if(!file.is_open())
	{
		cerr<<"file "<<filename<<" cannot be open!";
		return;
	}
	
	strcpy(dest_dir, "/tmp/chw412/");
	
	size_t found = filename.find_last_of("/");

	strcat(dest_dir, filename.substr(found + 1).c_str());

	fstream out(dest_dir, ios::out);

	string buffer;
	
	while(getline(file, buffer))
	{
		out<<buffer<<endl;
	}
}

int main(int argc, char ** argv)
{
	
	MPI::Init(argc, argv);

	rank = MPI::COMM_WORLD.Get_rank();
	size = MPI::COMM_WORLD.Get_size();

	optind = 1;
	opterr = 0;
	int result;
	
	while((result = getopt(argc, argv, "d:n:")) != -1)
	{
		switch((char)result)
		{
			case 'd':
				strcpy(dir, optarg);
				break;
			case '?':
				if (optopt == 'd')
					fprintf(stderr, "Option -%c requires an argument.\n", optopt);
				else if (isprint (optopt))
					fprintf(stderr, "Unknown option '-%c'.\n", optopt);
				else
					fprintf(stderr, "Unkown option character '\\x%x'.\n", optopt);
				return 1;
			default:
				abort();

		}
	}

	//Here we sucessfully get the value of N, which indicates the number of the most common words we need to output.
	//printf("N = %d\n", N);
	if(optind < argc) //there is no file(s) that need to be processed
		fprintf(stderr, "The output dir is /tmp/chw412/. So you do not have to designate another one! Files/Dirs designated are automatically omitted.\n");

	//test if the directory is empty string,
	//if it is, all processes exit.
	if(strcmp(dir, "") == 0)
	{
		fprintf(stderr, "You need to assign a directory using -d option!\n");
		exit(0);
	}

	//test if the directory name indicates a real directory rather
	//than a ordinary file.
	struct stat directory_information;
	stat(dir, &directory_information);
	if(!S_ISDIR(directory_information.st_mode))
	{
		fprintf(stderr, "Error: %s is not a directory!\n", dir);
		exit(0);
	}


	struct stat st;

	strcpy(dest_dir, "/tmp/chw412/");

	//If the destination directory does not exist
	//we just create a new directory called /tmp/chw412/
	if(stat(dest_dir, &st) != 0) 	
	{
		mkdir(dest_dir, 0777);
	}
	else
	{
		//if the destination directory does exist, 
		//we eliminate all non-hidden files in that folder
		struct dirent * entryptr;
		DIR * dirptr;
		dirptr = opendir(dest_dir);
		while((entryptr = readdir(dirptr)) != NULL)
		{
			if(entryptr->d_name[0] == '.')
				continue;
			
			strcpy(buffer, dest_dir);
			strcat(buffer, entryptr->d_name);
			unlink(buffer);
		}
		closedir(dirptr);
	}

	struct dirent * entryptr;
	DIR * dirptr;

	dirptr = opendir(dir);

	while((entryptr = readdir(dirptr)) != NULL)
	{
		//ommitting hidden files
		if(entryptr->d_name[0] == '.')
			continue;

		strcpy(buffer, dir);
		strcat(buffer, entryptr->d_name);

		process_this_file(string(buffer));		
	}
		
	closedir(dirptr);

	MPI::Finalize();
	return 0;
}

